﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using xycn.pluginsupport;
using xycn.framework.Common;
using xycn.pluginsupport.ControllerPlugins;
using xycn.pluginsupport.BaseHelperPlugins;
using System.Web;
using System.Text;
using Microsoft.Extensions.Primitives;
using System.Linq;

namespace xycn.framework.ControllerManagement
{


    /// <summary>
    /// 外部controller插件对应方法调用类
    /// </summary>
    public class ControllerInvoker
    {
        /// <summary>
        /// controller所在库信息
        /// </summary>
        public string fromLib = "";

        /// <summary>
        /// 所在命名空间
        /// </summary>
        public string Namespace = "";

        /// <summary>
        /// controller类名
        /// </summary>
        public string className = "";

        /// <summary>
        /// congroller类型
        /// </summary>
        public Type controllerType = null;

        /// <summary>
        /// congroller类型
        /// </summary>
        public Type controllerBaseType = null;

        /// <summary>
        /// 函数信息
        /// </summary>
        public MethodInfo methodInfor = null;

        /// <summary>
        /// 函数名
        /// </summary>
        public string methodName = "";

        /// <summary>
        /// 函数对应的处理http请求的类型
        /// </summary>
        public HttpMethodType httpMethodType = new HttpMethodType();

        /// <summary>
        /// 函数是否标记为通过HttpContext对象来处理Http请求
        /// </summary>
        public MethodAttribute methodAttrType;

        /// <summary>
        /// 定义基于原始HttpContext的http请求函数，效率更高，适用于
        /// 更深层次的开发
        /// </summary>
        public Func<HttpContext, Task> httpMethodWithContextFunc = null;

        /// <summary>
        /// 函数的HttpMethod或HttpMethoWithContext对象
        /// </summary>
        public object httpMethodAttr = null;

        /// <summary>
        /// 函数对应的路由属性
        /// </summary>
        public List<Route> routeAttrs = new List<Route>();

        /// <summary>
        /// 授权角色 true表示需要授权 false不需要授权 默认需要授权 liuxijin 20210329 
        /// </summary>
        public bool IsAuth { get; set; } = true;

        /// <summary>
        /// 函数需要输入的参数
        /// </summary>
        public List<MethodParmeter> Parameters =
            new List<MethodParmeter>();

        /// <summary>
        /// 函数返回类型
        /// </summary>
        public Type returnType = null;

        /// <summary>
        /// 调用本对像的，通过emit方式动态生成的静态函数委托
        /// 是实际映射到路由上的函数
        /// </summary>
        public RequestDelegate dynamicCaller = null;

        /// <summary>
        /// 创建Controller调用类
        /// </summary>
        /// <param name="bind_method"></param>
        public ControllerInvoker()
        {

        }

        /// <summary>
        /// 根据方法中的参数标记，提取参数值，以便输入到调用的controller函数
        /// </summary>
        private int BuildInputss(HttpContext context,
            out object[] parameter_objs, out string err_msg)
        {
            parameter_objs = new object[Parameters.Count];
            err_msg = "";

            int ret = 0;
            for (int i = 0; i < Parameters.Count; i++)
            {
                MethodParmeter parmeter = Parameters[i];
                //为避免提取参数时出现错误，导致参数错位，提前创建一个参数
                string qry;
                object obj = null;
                err_msg = "";

                //从查询字符串中
                if (parmeter.Attribute == "FromQuery")
                {
                    Microsoft.Extensions.Primitives.StringValues sv;
                    //qry = context.Request.Query[parmeter.Name];
                    if (context.Request.Query.TryGetValue(parmeter.Name, out sv))
                    {
                        qry = sv[0];
                        if (String2ObjectOfSpecific.Convert(qry, parmeter.parmeterType,
                            out obj, out err_msg)
                            < 0)
                        {
                            err_msg = "调用" +
                                fromLib + "的" +
                                className + "." +
                                methodName +
                                "方法时，提取参数值出现错误：" +
                                err_msg;
                            ret = -1;
                        }
                    }
                    else { qry = null; }
                }

                //从上传表单中获取数据
                if (parmeter.Attribute == "FromForm")
                {
                    //上传文件
                    if (parmeter.parmeterType.Name == "UploadFiles" &&
                        context.Request.Form.Files.Count > 0)
                    {
                        obj = new UploadFiles();
                        foreach (IFormFile file in context.Request.Form.Files)
                        {
                            UploadFile upload_file = new UploadFile()
                            {
                                contentType = file.ContentType,
                                fileName = file.FileName,
                                length = file.Length,
                                name = file.Name,
                                fileReaderStream = file.OpenReadStream()
                            };

                            ((UploadFiles)obj).uploadFiles.Add(upload_file);
                        }
                    }
                    else
                    {
                        //qry = context.Request.Form[parmeter.Name];
                        StringValues sv;
                        if (context.Request.Form.TryGetValue(parmeter.Name, out sv))
                        {
                            qry = sv[0];
                            if (String2ObjectOfSpecific.Convert(qry, parmeter.parmeterType,
                            out obj, out err_msg)
                            < 0)
                            {
                                err_msg = "调用" +
                                    fromLib + "的" +
                                    className + "." +
                                    methodName +
                                    "方法时，提取参数值出现错误：" +
                                    err_msg;
                                ret = -1;
                            }
                        }
                        else { qry = null; }
                    }
                }
                if (parmeter.Attribute == "FromHeader")
                {
                    //qry = context.Request.Headers[parmeter.Name];
                    StringValues sv;
                    if (context.Request.Headers.TryGetValue(parmeter.Name, out sv))
                    {
                        qry = sv[0];
                        if (String2ObjectOfSpecific.Convert(qry, parmeter.parmeterType,
                        out obj, out err_msg)
                        < 0)
                        {
                            err_msg = "调用" +
                                fromLib + "的" +
                                className + "." +
                                methodName +
                                "方法时，提取参数值出现错误：" +
                                err_msg;
                            ret = -1;
                        }
                    }
                    else { qry = null; }
                }
                if (parmeter.Attribute == "FromRoute" || parmeter.Attribute == "")
                {
                    object? temp_value;
                    //qry = context.Request.RouteValues[parmeter.Name].ToString();
                    if (context.Request.RouteValues.TryGetValue(parmeter.Name, out temp_value))
                    {
                        qry = (string)temp_value;
                        if (String2ObjectOfSpecific.Convert(qry, parmeter.parmeterType,
                        out obj, out err_msg)
                        < 0)
                        {
                            err_msg = "调用" +
                                fromLib + "的" +
                                className + "." +
                                methodName +
                                "方法时，提取参数值出现错误：" +
                                err_msg;
                            ret = -1;
                        }
                    }
                    else { qry = null; }
                }

                if (parmeter.Attribute == "FromBody")
                {
                    //根据[FromBody]属性，从body中提取字符串，反序列化为指定类型的
                    //对象后作为参数
                    System.IO.Pipelines.PipeReader pipe_reader = context.Request.BodyReader;
                    Stream body_stream = pipe_reader.AsStream(true);

                    if (parmeter.parmeterType.Name == "Stream")
                    {
                        obj = body_stream;
                    }
                    else
                    {
                        StreamReader reader = new StreamReader(body_stream);
                        string body_str = reader.ReadToEnd();

                        //尝试转化为基本数据类型
                        if (String2ObjectOfSpecific.Convert(
                            body_str, parmeter.parmeterType,
                            out obj, out err_msg) < 0)
                        {
                            //基本数据类型转化失败后，尝试进行反序列化
                            try
                            {
                                var options = new JsonSerializerOptions
                                {
                                    PropertyNameCaseInsensitive = true,
                                };

                                options.Converters.Add(new DateTimeConverterUsingDateTimeParse());

                                obj = JsonSerializer.Deserialize(body_str, parmeter.parmeterType, options);
                            }
                            catch (Exception ex)
                            {
                                //反序列化失败，直接将body的字符串作为参数
                                obj = body_str;
                                err_msg = "调用" +
                                    fromLib + "的" +
                                    className + "." +
                                    methodName +
                                    "方法时，从Body中提取字符串出现问题。" + ex.Message;
                                ret = -1;
                            }
                        }
                    }
                }

                parameter_objs[i] = obj;
            }
            return ret;
        }

        /// <summary>
        /// 根据绑定信息，调用controller插件
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task ControllerDelegate(HttpContext context)
        {
            //根据请求，创建输入参数
            object[] parameters = null;
            string err_msg = "";

            try
            {
                if (BuildInputss(context, out parameters, out err_msg) < 0)
                {
                    LogHelper.Error("ConrollerInvoker：" + err_msg,
                        Program.isDebugMode);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex, "解析输入参数出现错误：" + err_msg);
            }

            object controller;
            //实例化控制器
            if (CreateController(context, out controller, out err_msg) < 0)
            {
                LogHelper.Error(err_msg, Program.isDebugMode);

                CommonResponse error_response = new CommonResponse();
                error_response.Status = 500;
                error_response.Code = -1;
                error_response.Message = err_msg;
                WriteJsonResponse(error_response, context);
                await context.Response.CompleteAsync();
                return;
            }

            //根据绑定的controller插件信息，调用插件，执行具体代码
            //并利用统一回应消息，封装回应消息体
            //根据是否使用context标记，调用controller对应的Http请求处理方法
            if (methodAttrType == MethodAttribute.HttpMethodWithContext ||
            methodAttrType == MethodAttribute.ActionWithContext)
            {
                //tobemodified
                //考虑直接调用缓存的controller对象委托函数，以提高性能
                //await this.httpMethodWithContextFunc(context);
                //tobemodified over
                try
                {
                    methodInfor.Invoke(controller, new HttpContext[] { context });
                    //处理控制器设置的回应信息
                    HandelControllerContextResponse(context, controller);
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex, "调用处理原生HttpContext的方法\"" +
                        methodName + "\"处理请求失败。" + ex.Message, Program.isDebugMode);

                    CommonResponse novalue_response = new CommonResponse();
                    novalue_response.Status = 500;
                    novalue_response.Code = -1;
                    novalue_response.Message = "调用处理原生HttpContext的方法\"" +
                        methodName + "\"处理请求失败。" + ex.Message;
                    WriteJsonResponse(novalue_response, context);
                }
                await context.Response.CompleteAsync();
                return;
            }


            //调用返回值为void的控制器进行处理
            if (returnType.Name == "Void")
            {
                ResponseVoidReturn(context, controller, parameters);
                return;
            }

            //调用返回值类型为流的处理器进行流传输处理
            if (returnType.FullName == "System.IO.Stream")
            {
                ResponseStreamReturn(context, controller, parameters);
                return;
            }

            //调用返回值为DownloadFile对象的从控制器，进行下载文件处理
            if (returnType.Name == "DownloadFile")
            {
                await ResponseDownloadFile(controller, parameters, context);
                return;
            }

            //返回值为简单值、对象类型，则进行序列化
            CommonResponse obj_response = new CommonResponse();
            obj_response.Status = 200;
            obj_response.Code = 0;
            obj_response.Message = "OK";
            try
            {
                //缓存判断 hack 20210415 liuxijin
                dynamic dataCache = null;
                string md5key = "";
                var cacheType = GetDataCache(controller, parameters, ref dataCache, ref md5key);
                if (cacheType == 0)
                {
                    obj_response.ResultBody = dataCache;
                }
                else
                {
                    obj_response.ResultBody = methodInfor.Invoke(controller, parameters);
                }
                if (cacheType > 1)
                {
                    SetDataCache(md5key, obj_response.ResultBody, cacheType);
                }
                //缓存 endhack


                //处理控制器设置的回应信息
                HandelControllerContextResponse(context, controller);
            }
            catch (Exception ex)
            {
                obj_response.Status = 500;
                obj_response.Code = -1;
                obj_response.Message = "调用返回对象或简单值的控制器，\"" +
                        methodName + "\"处理请求失败" + ex.Message;

                LogHelper.Error(ex, "调用返回对象或简单值的控制器，\"" +
                        methodName + "\"处理请求失败" + ex.Message);
            }
            WriteJsonResponse(obj_response, context);
            await context.Response.CompleteAsync();
        }

        /// <summary>
        /// 创建控制器对象
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        private int CreateController(HttpContext context, out object controller, out string err_msg)
        {
            err_msg = "";
            try
            {
                controller = Activator.CreateInstance(controllerType);
            }
            catch (Exception ex)
            {
                controller = null;
                err_msg = "创建控制器实例出错。错误信息：" + ex.Message;
                return -1;
            }

            try
            {

                if (controllerBaseType.FullName ==
                    "xycn.pluginsupport.ControllerPlugins.BaseController")
                {
                    BaseController tp_controller = (BaseController)controller;
                    //设置httpcontext相关信息
                    tp_controller.controllerContext.localIP = context.Connection.LocalIpAddress.ToString();
                    tp_controller.controllerContext.localPort = context.Connection.LocalPort;
                    tp_controller.controllerContext.remoteIP = context.Connection.RemoteIpAddress.ToString();
                    tp_controller.controllerContext.remotePort = context.Connection.RemotePort;
                    tp_controller.controllerContext.TranItems = context.Items;

                    RequestInfo request_info = tp_controller.controllerContext.requestInfo;
                    request_info.bodyStream = context.Request.Body;
                    request_info.contentLength = context.Request.ContentLength;

                    request_info.contentType = context.Request.ContentType;
                    foreach (KeyValuePair<string, string> item in context.Request.Cookies)
                    {
                        request_info.cookieList.Add(
                            new KeyValuePair<string, string>(item.Key, item.Value));
                    }

                    if (context.Request.HasFormContentType)
                    {
                        foreach (KeyValuePair<string, StringValues> item in context.Request.Form)
                        {
                            foreach (string value in item.Value)
                            {
                                request_info.formDataList.Add(
                                new KeyValuePair<string, string>(item.Key, value));
                            }
                        }
                    }

                    request_info.scheme = context.Request.Scheme;
                    request_info.hasFormContentType = context.Request.HasFormContentType;
                    request_info.hasJsonContentType = context.Request.HasJsonContentType();

                    foreach (KeyValuePair<string, StringValues> item in context.Request.Headers)
                    {
                        foreach (string value in item.Value)
                        {
                            request_info.headersList.Add(new KeyValuePair<string, string>(item.Key, value));
                        }
                    }
                    request_info.host = context.Request.Host.Value;
                    request_info.isHttps = context.Request.IsHttps;
                    request_info.requestMethod = context.Request.Method;
                    request_info.path = context.Request.Path;
                    request_info.pathBase = context.Request.PathBase;
                    request_info.protocol = context.Request.Protocol;
                    request_info.queryString = context.Request.QueryString.Value;

                    foreach (KeyValuePair<string, StringValues> item in context.Request.Query)
                    {
                        foreach (string value in item.Value)
                        {
                            request_info.queryList.Add(
                                new KeyValuePair<string, string>(item.Key, value));
                        }
                    }

                    foreach (KeyValuePair<string, object> item in context.Request.RouteValues)
                    {
                        request_info.routeValues.Add(item.Key, item.Value);
                    }
                }
            }
            catch (Exception ex)
            {
                controller = null;
                err_msg = "创建控制器运行环境(ControllerContext)出错。错误信息：" + ex.Message;
                return -1;
            }
            return 0;
        }

        /// <summary>
        /// 处理控制器对象调用后，设置的回应信息项
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        private void HandelControllerContextResponse(HttpContext context, object controller)
        {
            try
            {
                if (controllerBaseType.FullName ==
                    "xycn.pluginsupport.ControllerPlugins.BaseController")
                {
                    ResponseInfo response_info =
                        ((BaseController)controller).controllerContext.responseInfo;

                    if (response_info.deleteCookies != null)
                    {
                        //删除响应中的cookie
                        foreach (string cookie_name in response_info.deleteCookies)
                        {
                            context.Response.Cookies.Delete(cookie_name);
                        }
                    }

                    if (response_info.newCookies != null)
                    {
                        //删除响应中的cookie
                        foreach (KeyValuePair<string, string> cookie in response_info.newCookies)
                        {
                            context.Response.Cookies.Append(cookie.Key, cookie.Value);
                        }
                    }

                    if (response_info.deleteHeaders != null)
                    {
                        //删除响应中的header
                        foreach (string header_name in response_info.deleteHeaders)
                        {
                            context.Response.Headers.Remove(header_name);
                        }
                    }

                    if (response_info.newHeaders != null)
                    {
                        //新增响应中头
                        foreach (KeyValuePair<string, string> header in response_info.newHeaders)
                        {
                            context.Response.Headers.Append(header.Key, header.Value);
                        }
                    }

                    if (response_info.ContentLength != null)
                        context.Response.ContentLength = response_info.ContentLength;

                    if (response_info.ContentType != null)
                        context.Response.ContentType = response_info.ContentType;

                    if (response_info.StatusCode != null)
                        context.Response.StatusCode = (int)response_info.StatusCode;

                    //设置重定向地址
                    if (response_info.redirectLocation != null)
                        context.Response.Redirect(response_info.redirectLocation);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex,
                    "创建控制器运行环境(ControllerContext)出错。错误信息：" +
                    ex.Message, Program.isDebugMode);
            }
        }

        /// <summary>
        /// 回应无返回值的控制器处理结果
        /// </summary>
        /// <param name="context"></param>
        /// <param name="controller"></param>
        /// <param name="parameters"></param>
        private void ResponseVoidReturn(HttpContext context,
            object controller, object[] parameters)
        {
            CommonResponse novalue_response = new CommonResponse();
            novalue_response.Status = 200;
            novalue_response.Code = 0;
            novalue_response.Message = "OK";
            try
            {
                methodInfor.Invoke(controller, parameters);
                //处理控制器设置的回应信息
                HandelControllerContextResponse(context, controller);
            }
            catch (Exception ex)
            {
                novalue_response.Status = 500;
                novalue_response.Code = -1;
                novalue_response.Message = "调用无返回值的控制器，\"" +
                    methodName + "\"处理请求失败" + ex.Message;

                LogHelper.Error(ex, "调用无返回值的控制器，\"" +
                    methodName + "\"处理请求失败" + ex.Message, Program.isDebugMode);
            }
            WriteJsonResponse(novalue_response, context);
            context.Response.CompleteAsync();
        }

        /// <summary>
        /// 回应处理流传输
        /// </summary>
        /// <param name="context"></param>
        /// <param name="controller"></param>
        /// <param name="parameters"></param>
        private void ResponseStreamReturn(HttpContext context, object controller, object[] parameters)
        {
            //调用controller处理函数，获取流对象
            Stream source_stream = null;

            try
            {
                source_stream = (Stream)methodInfor.Invoke(controller, parameters);
                //处理控制器设置的回应信息
                HandelControllerContextResponse(context, controller);
            }
            catch (Exception ex)
            {
                CommonResponse response = new CommonResponse();
                response.Status = 500;
                response.Code = -1;
                response.Message = "调用下载（写流）的控制器，\"" +
                    methodName + "\"处理请求失败。" + ex.Message;

                LogHelper.Error(ex, "调用下载（写流）的控制器，\"" +
                    methodName + "\"处理请求失败。" + ex.Message,
                    Program.isDebugMode);

                WriteJsonResponse(response, context);
                context.Response.CompleteAsync();
                return;
            }

            if (source_stream != null)
            {
                //设置下载文件的响应信息头
                context.Response.ContentType = "application/octet-stream";
                context.Response.ContentLength = source_stream.Length;

                System.IO.Pipelines.PipeWriter pipe_writer = context.Response.BodyWriter;
                Stream dest_stream = pipe_writer.AsStream();
                source_stream.CopyTo(dest_stream);
                source_stream.Close();
                source_stream.Dispose();
                pipe_writer.Complete();
                context.Response.CompleteAsync();
            }
        }

        /// <summary>
        /// 实现传送文件接口
        /// </summary>
        class DownloadFileImplement : IFileInfo
        {
            public bool Exists { get; set; }
            public bool IsDirectory { get; set; }
            public DateTimeOffset LastModified { get; set; }
            public long Length { get; set; }
            public string Name { get; set; }
            public string PhysicalPath { get; set; }
            public Stream fileStream = null;
            public Stream CreateReadStream()
            {
                return fileStream;
            }
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="parameters"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task ResponseDownloadFile(object controller, object[] parameters, HttpContext context)
        {
            DownloadFile download_file = null;
            try
            {
                download_file = (DownloadFile)methodInfor.Invoke(controller, parameters);
                //处理控制器设置的回应信息
                HandelControllerContextResponse(context, controller);
            }
            catch (Exception ex)
            {
                CommonResponse download_response = new CommonResponse();
                download_response.Status = 500;
                download_response.Code = -1;
                download_response.Message = "调用\"" +
                    methodName + "\"处理请求失败。" + ex.Message;

                LogHelper.Error(ex, "调用\"" +
                    methodName + "\"处理请求失败。" + ex.Message,
                    Program.isDebugMode);
            }

            if (download_file == null || download_file.fileStream == null)
            {
                CommonResponse novalue_response = new CommonResponse();
                novalue_response.Status = 400;
                novalue_response.Code = -1;
                novalue_response.Message = "Error";
                WriteJsonResponse(novalue_response, context);
                await context.Response.CompleteAsync();
                return;
            }

            DownloadFileImplement downloadFileImplement = new DownloadFileImplement()
            {
                Exists = true,
                IsDirectory = false,
                LastModified = DateTime.Now,
                Length = download_file.fileLength,
                Name = download_file.fileName,
                PhysicalPath = "",
                fileStream = download_file.fileStream
            };

            try
            {
                context.Response.Headers.Append("Cache-Control", "no-cache");
                context.Response.Headers.Append("Connection", "keep-alive");
                context.Response.ContentType = "application/octet-stream";
                context.Response.Headers.Append("Content-Disposition",
                    "attachment;filename=" +
                    HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(download_file.fileName)));
                context.Response.ContentLength = download_file.fileLength;
                downloadFileImplement.fileStream = download_file.fileStream;

                //支持断点续传,并等待文件发送结束后再关闭文件流
                await context.Response.SendFileAsync(downloadFileImplement,
                    download_file.offsetPosition,
                    download_file.fileLength - download_file.offsetPosition);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex, "读取文件内容并写流的时候，发生错误了\"" +
                        methodName + "\"处理请求失败" + ex.Message,
                        Program.isDebugMode);
            }

            download_file.fileStream.Close();
            download_file.fileStream.Dispose();
            await context.Response.CompleteAsync();
        }

        /// <summary>
        /// 返回响应结果
        /// </summary>
        /// <param name="response"></param>
        /// <param name="context"></param>
        private void WriteJsonResponse(CommonResponse response, HttpContext context)
        {
            //设置返回json是否采用缩进方式
            bool do_write_indented = false;
            if (Program.isDebugMode)
            {
                do_write_indented = true;
            }

            context.Response.ContentType = "application/json";

            /*
             * 采用这种方式，效率能达到同原生Asp.Net Core同样性能，但输出的时间类型会存在‘T’格式
             * Release 版处理性能为 > 6000次请求/秒
             */
            //context.Response.WriteAsJsonAsync(response, response.GetType());

            /*
             * 采用这种方式，添加option后，效率同样下降很多
             * Release 版处理性能为 > 2000次请求/秒
             */
            /*JsonSerializerOptions options = new(JsonSerializerDefaults.Web);
            {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                PropertyNameCaseInsensitive = true,
                //WriteIndented = do_write_indented
            };

            options.Converters.Add(new DateTimeConverterUsingDateTimeParse());
            context.Response.WriteAsJsonAsync(response, response.GetType(),options);*/


            /*
             * 采用这种方式，效率能达到同原生Asp.Net Core性能相差较大
             * Release 版处理性能为 > 2000次请求/秒
             */
            JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
            {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                PropertyNameCaseInsensitive = true,
                WriteIndented = do_write_indented
            };

            options.Converters.Add(new DateTimeConverterUsingDateTimeParse());

            byte[] jsonUtf8Bytes;
            jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(response, options);

            System.IO.Pipelines.PipeWriter response_writer =
                context.Response.BodyWriter;
            response_writer.WriteAsync(jsonUtf8Bytes);
            response_writer.FlushAsync();
        }

        /// <summary>
        /// 处理数据缓存 datacache -1未设置缓存 0设置了可直接使用，其他值为设置了但是无缓存，值为缓存时间
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="parameters"></param>
        /// <param name="dataCache"></param>
        /// <returns></returns>
        private int GetDataCache(object controller, object[] parameters, ref dynamic dataCache, ref string md5key)
        {
            if (DataCacheHelper.cacheHelper == null)
            {
                return -1;
            }
            var cacheAtts = methodInfor.GetCustomAttributesData().FirstOrDefault(p => p.AttributeType.FullName == typeof(DataCacheAttribute).FullName);
            if (cacheAtts != null)
            {
                int resSends = 0;
                var sends = cacheAtts.NamedArguments.FirstOrDefault(p => p.MemberName == nameof(DataCacheAttribute.CacheMinutes));
                if (int.TryParse(sends.TypedValue.Value.ToString(), out resSends))
                {
                    var key = methodInfor.DeclaringType.FullName + "." + methodInfor.Name + JsonSerializer.Serialize(parameters);
                    md5key = Md5.Encrypt32(key);
                    dataCache = DataCacheHelper.GetCache(md5key);
                    if (dataCache != null)
                    {
                        return 0;
                    }
                    else
                    {
                        return resSends;
                    }
                }
                else
                {
                    return -1;
                }
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 异步添加缓存
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="parameters"></param>
        /// <param name="dataCache"></param>
        /// <returns></returns>
        private void SetDataCache(string md5key, dynamic dataCache, int cacheType)
        {
            if (DataCacheHelper.cacheHelper == null)
            {
                return;
            }

            Task.Run(() =>
            {
                DataCacheHelper.SetCache(md5key, dataCache, cacheType);
            });
        }
    }

    /// <summary>
    /// json日期时间处理
    /// </summary>
    public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateTime.Parse(reader.GetString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }
}
